package com.lwt.service.impl;

import com.lwt.dao.OrderMapper;
import com.lwt.dao.StockMapper;
import com.lwt.dao.UserMapper;
import com.lwt.entity.Order;
import com.lwt.entity.Stock;
import com.lwt.entity.User;
import com.lwt.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @program: seckill
 * @author: 关键我是大怪
 * @create: 2021-11-11 20:03
 */
@Service
@Transactional
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    private StockMapper stockMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public int kill(Integer id, Integer userid, String md5) {

//        校验redis中秒杀商品是否超时
//        if (!stringRedisTemplate.hasKey("kill" + id)) {
//            throw new RuntimeException("当前商品的抢购活动已经结束~");
//        }

        //先验证签名
        String hashKey = "KEY_" + userid + "_" + id;
        String s = stringRedisTemplate.opsForValue().get(hashKey);
        if (s == null) {
            throw new RuntimeException("没有携带验证签名，请求不合法");
        }
        if (!s.equals(md5)) {
            throw new RuntimeException("当前请求数据不合法，稍后再试");
        }
        //校验库存
        Stock stock = checkStock(id);
        //更新库存
        updateSale(stock);
        //创建订单
        return createOrder(stock);
    }


    @Override
    public String getMd5(Integer id, Integer userid) {
        //验证userid 存在用户信息
        User user = userMapper.findById(userid);
        if (user == null) {
            throw new RuntimeException("用户信息不存在");
        }
        log.info("用户信息:[{}]", user.toString());
        //验证id 存在商品信息
        Stock stock = stockMapper.checkStock(id);
        if (stock == null) {
            throw new RuntimeException("商品信息不合法");
        }
        log.info("商品信息[{}]", stock.toString());
        //生成hashkey
        String hashKey = "KEY_" + userid + "_" + id;
        //生成md5 这里 !QS#是一个随机盐
        String key = DigestUtils.md5DigestAsHex((userid + id + "!QS#").getBytes());
        //生成md5 签名放入redis服务
        stringRedisTemplate.opsForValue().set(hashKey, key, 120, TimeUnit.SECONDS);
        log.info("Redis写入：[{}] [{}]", hashKey, key);

        return key;
    }

    @Override
    public int kill(Integer id) {

        //校验redis中秒杀商品是否超时
        if (!stringRedisTemplate.hasKey("kill" + id)) {
            throw new RuntimeException("当前商品的抢购活动已经结束~");
        }
        //校验库存
        Stock stock = checkStock(id);
        //更新库存
        updateSale(stock);
        //创建订单
        return createOrder(stock);
    }

    //校验库存
    private Stock checkStock(Integer id) {
        Stock stock = stockMapper.checkStock(id);
        if (stock.getSale().equals(stock.getCount())) {
            throw new RuntimeException("库存不足");
        }
        return stock;
    }

    //更新库存
    public void updateSale(Stock stock) {
        //在sql层面完成销量的+1 和 版本号的+1 并且根据商品id和版本号同时查询更新的产品
        int updateRows = stockMapper.updateSale(stock);
        if (updateRows == 0) {
            throw new RuntimeException("抢购失败，请重试");
        }
    }

    //创建订单
    private Integer createOrder(Stock stock) {
        Order order = new Order();
        order.setSid(stock.getId())
                .setName(stock.getName())
                .setCreateDate(new Date());
        orderMapper.createOrder(order);
        return order.getId();
    }
}
